package com.cyd.product_service.cluster.loadbalance;

import com.cyd.product_service.cluster.ClusterService;
import com.cyd.product_service.cluster.LoadBalance;

import java.util.List;
import java.util.Random;


/**
 * 带权重的随机负载均衡
 * Created by fangzhihong on 2017/11/24.
 */
public class WeightedRandomLoadBalance implements LoadBalance {

    private Random random = new Random();

    /**
     * 权重分配的负载均衡，此方法参考了dubbo的负载均衡写法
     * 参看com.alibaba.dubbo.rpc.cluster.loadbalance.RandomLoadBalance
     * @param services 服务列表
     * @return 被选出的服务
     */
    @Override
    public ClusterService select(List<ClusterService> services) {
        int length = services.size();// 总个数
        if (length == 1) {
            return services.get(0);
        }
        int totalWeight = 0;// 总权重
        boolean sameWeight = true;// 权重是否都一样
        for (int i = 0; i < length; i++) {
            int weight = services.get(i).getWeight();
            totalWeight += weight;// 累计总权重
            if (sameWeight && i > 0 && weight != services.get(i - 1).getWeight()) {
                sameWeight = false;// 计算所有权重是否一样
            }
        }
        if (totalWeight > 0 && !sameWeight) {
            // 如果权重不相同且权重大于0则按总权重数随机
            int offset = random.nextInt(totalWeight);
            // 并确定随机值落在哪个片断上
            for (ClusterService service : services) {
                offset -= service.getWeight();
                if (offset < 0) {
                    return service;
                }
            }
        }
        // 如果权重相同或权重为0则均等随机
        return services.get(random.nextInt(length));
    }
}
